
#pragma once

#include <WinDef.h>

#include <DXGI.h>
#include <D3D10_1.h>
#include <D3DX11.h>
#include <D3DX10math.h>

#include "Math\Quaternion.h"

class Quaternion;
class Vector4;

class Matrix4x4
{
public:
	Matrix4x4(const D3DXMATRIX& other);
    Matrix4x4(const Matrix4x4& other);
    Matrix4x4& operator = (const Matrix4x4& other);
    ~Matrix4x4();

	// Static constructors.
	//-----------------------------------------------
    static Matrix4x4 CreateZero();
    static Matrix4x4 CreateIdentity();

    static Matrix4x4 CreateTranslation(FLOAT x, FLOAT y, FLOAT z);
    static Matrix4x4 CreateTranslation(const Vector4& vector);

    static Matrix4x4 CreateRotation(FLOAT x, FLOAT y, FLOAT z, FLOAT angle);
    static Matrix4x4 CreateRotation(const Vector4& axis, FLOAT angle);

    static Matrix4x4 CreateScale(FLOAT dx, FLOAT dy, FLOAT dz);
    static Matrix4x4 CreateScale(const Vector4& scale);

	// Getters & Setters.
	//-----------------------------------------------
	FLOAT& operator () (UINT row, UINT column);
	const FLOAT& operator () (UINT row, UINT column) const;
	
	Vector4 GetRow(UINT index) const;
	VOID SetRow(UINT index, const Vector4& row);
	VOID SetRow(UINT index, FLOAT x, FLOAT y, FLOAT z, FLOAT w);
	
	Vector4 GetColumn(UINT index) const;
	VOID SetColumn(UINT index, const Vector4& column);
	VOID SetColumn(UINT index, FLOAT x, FLOAT y, FLOAT z, FLOAT w);

	// Operations.
	//-----------------------------------------------
    Matrix4x4 InverseOrthonormal() const;
    Matrix4x4 Orthonormalize() const;
    Matrix4x4 Transpose() const;

	// Operators.
	//-----------------------------------------------
    BOOL operator == (const Matrix4x4& other) const;
    BOOL operator != (const Matrix4x4& other) const;

    Matrix4x4 Mul(const Matrix4x4& other) const;
    Matrix4x4 operator * (const Matrix4x4& other) const;
    Matrix4x4& operator *= (const Matrix4x4& other);
	
	Matrix4x4 Mul(FLOAT  factor) const;

	Matrix4x4 operator - () const;

    Vector4 Mul(const Vector4& other) const;
    Vector4 operator * (const Vector4& other) const;

	// Cast operators.
	//-----------------------------------------------
    operator Quaternion() const;
	operator D3DXMATRIX() const;
	
private:
    Matrix4x4();

	// Attributes.
	//-----------------------------------------------
    FLOAT m_matrix[16];	// Row major order.
};

Matrix4x4 operator * (const Matrix4x4& matrix, FLOAT factor);
Matrix4x4 operator * (FLOAT factor, const Matrix4x4& matrix);